一、HA架構工作背景
HDFS集群中的nameNode存在單點故障因素。對于只有一個nameNode工作的集群來說,一旦nameNode出現意外情況,會導致整個集群無法工作,直到nameNode重新啟動。
為了解決上述問題,Hadoop給出了高容錯,高可用的HA方案:一個HDFS集群至少存在兩個nameNode,一個nameNode處在active(主)狀態,其他nameNode處在standby(備)狀態。一旦處于activate狀態的nameNode發生意外,其他處于standby狀態的nameNode立即搶占activate的臨時節點,代替發生意外的nameNode繼續對外提供服務,從而保證了整個HDFS集群處在正常工作狀態。
二、主備數據同步
想要備nameNode接替主nameNode工作,那么必須保證備nameNode和主nameNode擁有相同的內存數據。
主nameNode主要有以下數據需要進行頻繁同步:edits log(日志)、block列表信息以及DataNode心跳檢測
2.1首先說日志的同步:
同步edits log數據是借助第三方JNN( Journal Nodes )提供的服務。客戶端對主nameNode操作,主nameNode將edits log寫到JNN集群,備nameNode從JNN集群上讀取數據,同步內存數據。可是主nameNode發生意外,導致JNN集群上各服務器上的數據不一致怎么辦呢?JNN集群最少有三臺服務器,一旦JNN服務器上的數據不一致,立即進行投票選舉,通過過半機制保證數據的一致性(即以多數為準),舍掉與多數不一致的數據,然后在將數據同步給舍掉數據的服務器,保證了數據的一致性。
2.2、介紹一下JNN
JNN的過半機制:
如果主nameNode向三臺JNN寫數據,只要保證過半JNN寫成功,就返回成功, JNN根據過半機制,進行數據在三臺JNN上同步。
最終一致性:最終三臺JNN上的edits信息是一致的。
JNN上的edits只能有一臺nameNode寫信息,防止腦裂。
2.3、block列表的同步:
DataNode主動向各臺nameNode發送block列表信息和心跳。從而保證了主備之間block的一致性。
2.4、合并fsimages與edits
原來HDFS上的secondarynameNode的合并fsimages(鏡像)與edits(日志) 文件的工作,現在交給備nameNode進行,備用nameNode一小時合并一次并推送給主nameNode,在不滿一小時的情況下,如果edits文件的操作達到100w,也要進行合并。
三、自動切換nameNode
主nameNode和備nameNode的切換時自動切換的,通過zookeeper集群來完成!
首先添加zookeeper集群,在每個nameNode上運行一個zkfc進程(zkfc是zookeeper的客戶端)。zkfc要和zookeeper集群保持長連接和心跳。
在集群啟動的時候,兩個NameNode都處于standby狀態, 兩個nameNode的各自的zkfc要向zookeeper集群搶占創建一個臨時節點,該臨時節點保存了主nameNode的信息,哪個zkfc創建成功,則哪個zkfc所在主機上的nameNode為主nameNode。
nameNode上的zkfc要監控主nameNode創建的臨時節點,一旦主nameNode出現故障,zkfc將刪除該臨時節點(實際上是因為主nameNode上的zkfc不能和zookeeper集群保持心跳連接,臨時節點消失),臨時節點消失,則備nameNode上的zkfc要向zookeeper集群搶占創建臨時節點,如果創建成功,備nameNode升級為主nameNode。
在備份nameNode升級為主nameNode之前,要和原來的nameNode通信,確保原來的nameNode已經不能提供服務。如果原來的nameNode是由于網絡延遲等原因導致的臨時節點消失(也就是說還能提供服務),則殺死原來的nameNode。